package net.minecraft.client.renderer;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import net.minecraft.client.Minecraft;
import net.minecraft.src.Config;
import net.minecraft.util.Util;

import org.lwjgl.Sys;
import org.lwjgl.opengl.ARBBufferObject;
import org.lwjgl.opengl.ARBFramebufferObject;
import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.ContextCapabilities;
import org.lwjgl.opengl.EXTBlendFuncSeparate;
import org.lwjgl.opengl.EXTFramebufferObject;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL14;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GLContext;

import com.kilo.mod.ModuleManager;
import com.kilo.mod.all.WallHack;

public class OpenGlHelper
{
    public static boolean nvidia;
    public static int GL_FRAMEBUFFER;
    public static int GL_RENDERBUFFER;
    public static int GL_COLOR_ATTACHMENT0;
    public static int GL_DEPTH_ATTACHMENT;
    public static int GL_FRAMEBUFFER_COMPLETE;
    public static int GL_FB_INCOMPLETE_ATTACHMENT;
    public static int GL_FB_INCOMPLETE_MISS_ATTACH;
    public static int GL_FB_INCOMPLETE_DRAW_BUFFER;
    public static int GL_FB_INCOMPLETE_READ_BUFFER;
    private static int framebufferType;
    public static boolean framebufferSupported;
    private static boolean shadersAvailable;
    private static boolean arbShaders;
    public static int GL_LINK_STATUS;
    public static int GL_COMPILE_STATUS;
    public static int GL_VERTEX_SHADER;
    public static int GL_FRAGMENT_SHADER;
    private static boolean arbMultitexture;

    /**
     * An OpenGL constant corresponding to GL_TEXTURE0, used when setting data pertaining to auxiliary OpenGL texture
     * units.
     */
    public static int defaultTexUnit;

    /**
     * An OpenGL constant corresponding to GL_TEXTURE1, used when setting data pertaining to auxiliary OpenGL texture
     * units.
     */
    public static int lightmapTexUnit;
    public static int GL_TEXTURE2;
    private static boolean arbTextureEnvCombine;
    public static int GL_COMBINE;
    public static int GL_INTERPOLATE;
    public static int GL_PRIMARY_COLOR;
    public static int GL_CONSTANT;
    public static int GL_PREVIOUS;
    public static int GL_COMBINE_RGB;
    public static int GL_SOURCE0_RGB;
    public static int GL_SOURCE1_RGB;
    public static int GL_SOURCE2_RGB;
    public static int GL_OPERAND0_RGB;
    public static int GL_OPERAND1_RGB;
    public static int GL_OPERAND2_RGB;
    public static int GL_COMBINE_ALPHA;
    public static int GL_SOURCE0_ALPHA;
    public static int GL_SOURCE1_ALPHA;
    public static int GL_SOURCE2_ALPHA;
    public static int GL_OPERAND0_ALPHA;
    public static int GL_OPERAND1_ALPHA;
    public static int GL_OPERAND2_ALPHA;
    private static boolean openGL14;
    public static boolean extBlendFuncSeparate;
    public static boolean openGL21;
    public static boolean shadersSupported;
    private static String logText = "";
    public static boolean vboSupported;
    private static boolean arbVbo;
    public static int GL_ARRAY_BUFFER;
    public static int GL_STATIC_DRAW;
    public static float lastBrightnessX = 0.0F;
    public static float lastBrightnessY = 0.0F;

    /**
     * Initializes the texture constants to be used when rendering lightmap values
     */
    public static void initializeTextures()
    {
        Config.initDisplay();
        ContextCapabilities var0 = GLContext.getCapabilities();
        arbMultitexture = var0.GL_ARB_multitexture && !var0.OpenGL13;
        arbTextureEnvCombine = var0.GL_ARB_texture_env_combine && !var0.OpenGL13;

        if (arbMultitexture)
        {
            logText = logText + "Using ARB_multitexture.\n";
            defaultTexUnit = 33984;
            lightmapTexUnit = 33985;
            GL_TEXTURE2 = 33986;
        }
        else
        {
            logText = logText + "Using GL 1.3 multitexturing.\n";
            defaultTexUnit = 33984;
            lightmapTexUnit = 33985;
            GL_TEXTURE2 = 33986;
        }

        if (arbTextureEnvCombine)
        {
            logText = logText + "Using ARB_texture_env_combine.\n";
            GL_COMBINE = 34160;
            GL_INTERPOLATE = 34165;
            GL_PRIMARY_COLOR = 34167;
            GL_CONSTANT = 34166;
            GL_PREVIOUS = 34168;
            GL_COMBINE_RGB = 34161;
            GL_SOURCE0_RGB = 34176;
            GL_SOURCE1_RGB = 34177;
            GL_SOURCE2_RGB = 34178;
            GL_OPERAND0_RGB = 34192;
            GL_OPERAND1_RGB = 34193;
            GL_OPERAND2_RGB = 34194;
            GL_COMBINE_ALPHA = 34162;
            GL_SOURCE0_ALPHA = 34184;
            GL_SOURCE1_ALPHA = 34185;
            GL_SOURCE2_ALPHA = 34186;
            GL_OPERAND0_ALPHA = 34200;
            GL_OPERAND1_ALPHA = 34201;
            GL_OPERAND2_ALPHA = 34202;
        }
        else
        {
            logText = logText + "Using GL 1.3 texture combiners.\n";
            GL_COMBINE = 34160;
            GL_INTERPOLATE = 34165;
            GL_PRIMARY_COLOR = 34167;
            GL_CONSTANT = 34166;
            GL_PREVIOUS = 34168;
            GL_COMBINE_RGB = 34161;
            GL_SOURCE0_RGB = 34176;
            GL_SOURCE1_RGB = 34177;
            GL_SOURCE2_RGB = 34178;
            GL_OPERAND0_RGB = 34192;
            GL_OPERAND1_RGB = 34193;
            GL_OPERAND2_RGB = 34194;
            GL_COMBINE_ALPHA = 34162;
            GL_SOURCE0_ALPHA = 34184;
            GL_SOURCE1_ALPHA = 34185;
            GL_SOURCE2_ALPHA = 34186;
            GL_OPERAND0_ALPHA = 34200;
            GL_OPERAND1_ALPHA = 34201;
            GL_OPERAND2_ALPHA = 34202;
        }

        extBlendFuncSeparate = var0.GL_EXT_blend_func_separate && !var0.OpenGL14;
        openGL14 = var0.OpenGL14 || var0.GL_EXT_blend_func_separate;
        framebufferSupported = openGL14 && (var0.GL_ARB_framebuffer_object || var0.GL_EXT_framebuffer_object || var0.OpenGL30);

        if (framebufferSupported)
        {
            logText = logText + "Using framebuffer objects because ";

            if (var0.OpenGL30)
            {
                logText = logText + "OpenGL 3.0 is supported and separate blending is supported.\n";
                framebufferType = 0;
                GL_FRAMEBUFFER = 36160;
                GL_RENDERBUFFER = 36161;
                GL_COLOR_ATTACHMENT0 = 36064;
                GL_DEPTH_ATTACHMENT = 36096;
                GL_FRAMEBUFFER_COMPLETE = 36053;
                GL_FB_INCOMPLETE_ATTACHMENT = 36054;
                GL_FB_INCOMPLETE_MISS_ATTACH = 36055;
                GL_FB_INCOMPLETE_DRAW_BUFFER = 36059;
                GL_FB_INCOMPLETE_READ_BUFFER = 36060;
            }
            else if (var0.GL_ARB_framebuffer_object)
            {
                logText = logText + "ARB_framebuffer_object is supported and separate blending is supported.\n";
                framebufferType = 1;
                GL_FRAMEBUFFER = 36160;
                GL_RENDERBUFFER = 36161;
                GL_COLOR_ATTACHMENT0 = 36064;
                GL_DEPTH_ATTACHMENT = 36096;
                GL_FRAMEBUFFER_COMPLETE = 36053;
                GL_FB_INCOMPLETE_MISS_ATTACH = 36055;
                GL_FB_INCOMPLETE_ATTACHMENT = 36054;
                GL_FB_INCOMPLETE_DRAW_BUFFER = 36059;
                GL_FB_INCOMPLETE_READ_BUFFER = 36060;
            }
            else if (var0.GL_EXT_framebuffer_object)
            {
                logText = logText + "EXT_framebuffer_object is supported.\n";
                framebufferType = 2;
                GL_FRAMEBUFFER = 36160;
                GL_RENDERBUFFER = 36161;
                GL_COLOR_ATTACHMENT0 = 36064;
                GL_DEPTH_ATTACHMENT = 36096;
                GL_FRAMEBUFFER_COMPLETE = 36053;
                GL_FB_INCOMPLETE_MISS_ATTACH = 36055;
                GL_FB_INCOMPLETE_ATTACHMENT = 36054;
                GL_FB_INCOMPLETE_DRAW_BUFFER = 36059;
                GL_FB_INCOMPLETE_READ_BUFFER = 36060;
            }
        }
        else
        {
            logText = logText + "Not using framebuffer objects because ";
            logText = logText + "OpenGL 1.4 is " + (var0.OpenGL14 ? "" : "not ") + "supported, ";
            logText = logText + "EXT_blend_func_separate is " + (var0.GL_EXT_blend_func_separate ? "" : "not ") + "supported, ";
            logText = logText + "OpenGL 3.0 is " + (var0.OpenGL30 ? "" : "not ") + "supported, ";
            logText = logText + "ARB_framebuffer_object is " + (var0.GL_ARB_framebuffer_object ? "" : "not ") + "supported, and ";
            logText = logText + "EXT_framebuffer_object is " + (var0.GL_EXT_framebuffer_object ? "" : "not ") + "supported.\n";
        }

        openGL21 = var0.OpenGL21;
        shadersAvailable = openGL21 || var0.GL_ARB_vertex_shader && var0.GL_ARB_fragment_shader && var0.GL_ARB_shader_objects;
        logText = logText + "Shaders are " + (shadersAvailable ? "" : "not ") + "available because ";

        if (shadersAvailable)
        {
            if (var0.OpenGL21)
            {
                logText = logText + "OpenGL 2.1 is supported.\n";
                arbShaders = false;
                GL_LINK_STATUS = 35714;
                GL_COMPILE_STATUS = 35713;
                GL_VERTEX_SHADER = 35633;
                GL_FRAGMENT_SHADER = 35632;
            }
            else
            {
                logText = logText + "ARB_shader_objects, ARB_vertex_shader, and ARB_fragment_shader are supported.\n";
                arbShaders = true;
                GL_LINK_STATUS = 35714;
                GL_COMPILE_STATUS = 35713;
                GL_VERTEX_SHADER = 35633;
                GL_FRAGMENT_SHADER = 35632;
            }
        }
        else
        {
            logText = logText + "OpenGL 2.1 is " + (var0.OpenGL21 ? "" : "not ") + "supported, ";
            logText = logText + "ARB_shader_objects is " + (var0.GL_ARB_shader_objects ? "" : "not ") + "supported, ";
            logText = logText + "ARB_vertex_shader is " + (var0.GL_ARB_vertex_shader ? "" : "not ") + "supported, and ";
            logText = logText + "ARB_fragment_shader is " + (var0.GL_ARB_fragment_shader ? "" : "not ") + "supported.\n";
        }

        shadersSupported = framebufferSupported && shadersAvailable;
        nvidia = GL11.glGetString(GL11.GL_VENDOR).toLowerCase().contains("nvidia");
        arbVbo = !var0.OpenGL15 && var0.GL_ARB_vertex_buffer_object;
        vboSupported = var0.OpenGL15 || arbVbo;
        logText = logText + "VBOs are " + (vboSupported ? "" : "not ") + "available because ";

        if (vboSupported)
        {
            if (arbVbo)
            {
                logText = logText + "ARB_vertex_buffer_object is supported.\n";
                GL_STATIC_DRAW = 35044;
                GL_ARRAY_BUFFER = 34962;
            }
            else
            {
                logText = logText + "OpenGL 1.5 is supported.\n";
                GL_STATIC_DRAW = 35044;
                GL_ARRAY_BUFFER = 34962;
            }
        }
    }

    public static boolean areShadersSupported()
    {
        return shadersSupported;
    }

    public static String getLogText()
    {
        return logText;
    }

    public static int glGetProgrami(int program, int pname)
    {
        return arbShaders ? ARBShaderObjects.glGetObjectParameteriARB(program, pname) : GL20.glGetProgrami(program, pname);
    }

    public static void glAttachShader(int program, int shaderIn)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glAttachObjectARB(program, shaderIn);
        }
        else
        {
            GL20.glAttachShader(program, shaderIn);
        }
    }

    public static void glDeleteShader(int p_153180_0_)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glDeleteObjectARB(p_153180_0_);
        }
        else
        {
            GL20.glDeleteShader(p_153180_0_);
        }
    }

    /**
     * creates a shader with the given mode and returns the GL id. params: mode
     */
    public static int glCreateShader(int type)
    {
        return arbShaders ? ARBShaderObjects.glCreateShaderObjectARB(type) : GL20.glCreateShader(type);
    }

    public static void glShaderSource(int shaderIn, ByteBuffer string)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glShaderSourceARB(shaderIn, string);
        }
        else
        {
            GL20.glShaderSource(shaderIn, string);
        }
    }

    public static void glCompileShader(int shaderIn)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glCompileShaderARB(shaderIn);
        }
        else
        {
            GL20.glCompileShader(shaderIn);
        }
    }

    public static int glGetShaderi(int shaderIn, int pname)
    {
        return arbShaders ? ARBShaderObjects.glGetObjectParameteriARB(shaderIn, pname) : GL20.glGetShaderi(shaderIn, pname);
    }

    public static String glGetShaderInfoLog(int shaderIn, int maxLength)
    {
        return arbShaders ? ARBShaderObjects.glGetInfoLogARB(shaderIn, maxLength) : GL20.glGetShaderInfoLog(shaderIn, maxLength);
    }

    public static String glGetProgramInfoLog(int program, int maxLength)
    {
        return arbShaders ? ARBShaderObjects.glGetInfoLogARB(program, maxLength) : GL20.glGetProgramInfoLog(program, maxLength);
    }

    public static void glUseProgram(int program)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUseProgramObjectARB(program);
        }
        else
        {
            GL20.glUseProgram(program);
        }
    }

    public static int glCreateProgram()
    {
        return arbShaders ? ARBShaderObjects.glCreateProgramObjectARB() : GL20.glCreateProgram();
    }

    public static void glDeleteProgram(int program)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glDeleteObjectARB(program);
        }
        else
        {
            GL20.glDeleteProgram(program);
        }
    }

    public static void glLinkProgram(int program)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glLinkProgramARB(program);
        }
        else
        {
            GL20.glLinkProgram(program);
        }
    }

    public static int glGetUniformLocation(int programObj, CharSequence name)
    {
        return arbShaders ? ARBShaderObjects.glGetUniformLocationARB(programObj, name) : GL20.glGetUniformLocation(programObj, name);
    }

    public static void glUniform1(int location, IntBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform1ARB(location, values);
        }
        else
        {
            GL20.glUniform1(location, values);
        }
    }

    public static void glUniform1i(int location, int v0)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform1iARB(location, v0);
        }
        else
        {
            GL20.glUniform1i(location, v0);
        }
    }

    public static void glUniform1(int location, FloatBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform1ARB(location, values);
        }
        else
        {
            GL20.glUniform1(location, values);
        }
    }

    public static void glUniform2(int location, IntBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform2ARB(location, values);
        }
        else
        {
            GL20.glUniform2(location, values);
        }
    }

    public static void glUniform2(int location, FloatBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform2ARB(location, values);
        }
        else
        {
            GL20.glUniform2(location, values);
        }
    }

    public static void glUniform3(int location, IntBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform3ARB(location, values);
        }
        else
        {
            GL20.glUniform3(location, values);
        }
    }

    public static void glUniform3(int location, FloatBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform3ARB(location, values);
        }
        else
        {
            GL20.glUniform3(location, values);
        }
    }

    public static void glUniform4(int location, IntBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform4ARB(location, values);
        }
        else
        {
            GL20.glUniform4(location, values);
        }
    }

    public static void glUniform4(int location, FloatBuffer values)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniform4ARB(location, values);
        }
        else
        {
            GL20.glUniform4(location, values);
        }
    }

    public static void glUniformMatrix2(int location, boolean transpose, FloatBuffer matrices)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniformMatrix2ARB(location, transpose, matrices);
        }
        else
        {
            GL20.glUniformMatrix2(location, transpose, matrices);
        }
    }

    public static void glUniformMatrix3(int location, boolean transpose, FloatBuffer matrices)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniformMatrix3ARB(location, transpose, matrices);
        }
        else
        {
            GL20.glUniformMatrix3(location, transpose, matrices);
        }
    }

    public static void glUniformMatrix4(int location, boolean transpose, FloatBuffer matrices)
    {
        if (arbShaders)
        {
            ARBShaderObjects.glUniformMatrix4ARB(location, transpose, matrices);
        }
        else
        {
            GL20.glUniformMatrix4(location, transpose, matrices);
        }
    }

    public static int glGetAttribLocation(int p_153164_0_, CharSequence p_153164_1_)
    {
        return arbShaders ? ARBVertexShader.glGetAttribLocationARB(p_153164_0_, p_153164_1_) : GL20.glGetAttribLocation(p_153164_0_, p_153164_1_);
    }

    public static int glGenBuffers()
    {
        return arbVbo ? ARBBufferObject.glGenBuffersARB() : GL15.glGenBuffers();
    }

    public static void glBindBuffer(int target, int buffer)
    {
        if (arbVbo)
        {
            ARBBufferObject.glBindBufferARB(target, buffer);
        }
        else
        {
            GL15.glBindBuffer(target, buffer);
        }
    }

    public static void glBufferData(int target, ByteBuffer data, int usage)
    {
        if (arbVbo)
        {
            ARBBufferObject.glBufferDataARB(target, data, usage);
        }
        else
        {
            GL15.glBufferData(target, data, usage);
        }
    }

    public static void glDeleteBuffers(int buffer)
    {
        if (arbVbo)
        {
            ARBBufferObject.glDeleteBuffersARB(buffer);
        }
        else
        {
            GL15.glDeleteBuffers(buffer);
        }
    }

    public static boolean useVbo()
    {
        return Config.isMultiTexture() ? false : vboSupported && Minecraft.getMinecraft().gameSettings.useVbo;
    }

    public static void glBindFramebuffer(int target, int framebufferIn)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glBindFramebuffer(target, framebufferIn);
                    break;

                case 1:
                    ARBFramebufferObject.glBindFramebuffer(target, framebufferIn);
                    break;

                case 2:
                    EXTFramebufferObject.glBindFramebufferEXT(target, framebufferIn);
            }
        }
    }

    public static void glBindRenderbuffer(int target, int renderbuffer)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glBindRenderbuffer(target, renderbuffer);
                    break;

                case 1:
                    ARBFramebufferObject.glBindRenderbuffer(target, renderbuffer);
                    break;

                case 2:
                    EXTFramebufferObject.glBindRenderbufferEXT(target, renderbuffer);
            }
        }
    }

    public static void glDeleteRenderbuffers(int renderbuffer)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glDeleteRenderbuffers(renderbuffer);
                    break;

                case 1:
                    ARBFramebufferObject.glDeleteRenderbuffers(renderbuffer);
                    break;

                case 2:
                    EXTFramebufferObject.glDeleteRenderbuffersEXT(renderbuffer);
            }
        }
    }

    public static void glDeleteFramebuffers(int framebufferIn)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glDeleteFramebuffers(framebufferIn);
                    break;

                case 1:
                    ARBFramebufferObject.glDeleteFramebuffers(framebufferIn);
                    break;

                case 2:
                    EXTFramebufferObject.glDeleteFramebuffersEXT(framebufferIn);
            }
        }
    }

    /**
     * Calls the appropriate glGenFramebuffers method and returns the newly created fbo, or returns -1 if not supported.
     */
    public static int glGenFramebuffers()
    {
        if (!framebufferSupported)
        {
            return -1;
        }
        else
        {
            switch (framebufferType)
            {
                case 0:
                    return GL30.glGenFramebuffers();

                case 1:
                    return ARBFramebufferObject.glGenFramebuffers();

                case 2:
                    return EXTFramebufferObject.glGenFramebuffersEXT();

                default:
                    return -1;
            }
        }
    }

    public static int glGenRenderbuffers()
    {
        if (!framebufferSupported)
        {
            return -1;
        }
        else
        {
            switch (framebufferType)
            {
                case 0:
                    return GL30.glGenRenderbuffers();

                case 1:
                    return ARBFramebufferObject.glGenRenderbuffers();

                case 2:
                    return EXTFramebufferObject.glGenRenderbuffersEXT();

                default:
                    return -1;
            }
        }
    }

    public static void glRenderbufferStorage(int target, int internalFormat, int width, int height)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glRenderbufferStorage(target, internalFormat, width, height);
                    break;

                case 1:
                    ARBFramebufferObject.glRenderbufferStorage(target, internalFormat, width, height);
                    break;

                case 2:
                    EXTFramebufferObject.glRenderbufferStorageEXT(target, internalFormat, width, height);
            }
        }
    }

    public static void glFramebufferRenderbuffer(int target, int attachment, int renderBufferTarget, int renderBuffer)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glFramebufferRenderbuffer(target, attachment, renderBufferTarget, renderBuffer);
                    break;

                case 1:
                    ARBFramebufferObject.glFramebufferRenderbuffer(target, attachment, renderBufferTarget, renderBuffer);
                    break;

                case 2:
                    EXTFramebufferObject.glFramebufferRenderbufferEXT(target, attachment, renderBufferTarget, renderBuffer);
            }
        }
    }

    public static int glCheckFramebufferStatus(int target)
    {
        if (!framebufferSupported)
        {
            return -1;
        }
        else
        {
            switch (framebufferType)
            {
                case 0:
                    return GL30.glCheckFramebufferStatus(target);

                case 1:
                    return ARBFramebufferObject.glCheckFramebufferStatus(target);

                case 2:
                    return EXTFramebufferObject.glCheckFramebufferStatusEXT(target);

                default:
                    return -1;
            }
        }
    }

    public static void glFramebufferTexture2D(int target, int attachment, int textarget, int texture, int level)
    {
        if (framebufferSupported)
        {
            switch (framebufferType)
            {
                case 0:
                    GL30.glFramebufferTexture2D(target, attachment, textarget, texture, level);
                    break;

                case 1:
                    ARBFramebufferObject.glFramebufferTexture2D(target, attachment, textarget, texture, level);
                    break;

                case 2:
                    EXTFramebufferObject.glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
            }
        }
    }

    /**
     * Sets the current lightmap texture to the specified OpenGL constant
     */
    public static void setActiveTexture(int texture)
    {
        if (arbMultitexture)
        {
            ARBMultitexture.glActiveTextureARB(texture);
        }
        else
        {
            GL13.glActiveTexture(texture);
        }
    }

    /**
     * Sets the current lightmap texture to the specified OpenGL constant
     */
    public static void setClientActiveTexture(int texture)
    {
        if (arbMultitexture)
        {
            ARBMultitexture.glClientActiveTextureARB(texture);
        }
        else
        {
            GL13.glClientActiveTexture(texture);
        }
    }

    /**
     * Sets the current coordinates of the given lightmap texture
     */
    public static void setLightmapTextureCoords(int target, float p_77475_1_, float p_77475_2_)
    {
        if (ModuleManager.get("wallhack").active) {
        	p_77475_1_ = 240;
        	p_77475_2_ = 240;
        }
        
        if (arbMultitexture)
        {
            ARBMultitexture.glMultiTexCoord2fARB(target, p_77475_1_, p_77475_2_);
        }
        else
        {
            GL13.glMultiTexCoord2f(target, p_77475_1_, p_77475_2_);
        }

        if (target == lightmapTexUnit)
        {
            lastBrightnessX = p_77475_1_;
            lastBrightnessY = p_77475_2_;
        }
    }

    public static void glBlendFunc(int sFactorRGB, int dFactorRGB, int sfactorAlpha, int dfactorAlpha)
    {
        if (openGL14)
        {
            if (extBlendFuncSeparate)
            {
                EXTBlendFuncSeparate.glBlendFuncSeparateEXT(sFactorRGB, dFactorRGB, sfactorAlpha, dfactorAlpha);
            }
            else
            {
                GL14.glBlendFuncSeparate(sFactorRGB, dFactorRGB, sfactorAlpha, dfactorAlpha);
            }
        }
        else
        {
            GL11.glBlendFunc(sFactorRGB, dFactorRGB);
        }
    }

    public static boolean isFramebufferEnabled()
    {
        return Config.getAntialiasingLevel() > 0 ? false : framebufferSupported && Minecraft.getMinecraft().gameSettings.fboEnable;
    }

    public static void openFile(File fileIn) {
		String s = fileIn.getAbsolutePath();

		if (Util.getOSType() == Util.EnumOS.OSX) {
			try {
				//LOGGER.info(s);
				Runtime.getRuntime().exec(new String[] { "/usr/bin/open", s });
				return;
			} catch (IOException ioexception11) {
			//	LOGGER.error("Couldn\'t open file", ioexception11);
			}
		} else if (Util.getOSType() == Util.EnumOS.WINDOWS) {
			String s1 = String.format("cmd.exe /C start \"Open file\" \"%s\"", new Object[] { s });

			try {
				Runtime.getRuntime().exec(s1);
				return;
			} catch (IOException ioexception1) {
			//	LOGGER.error("Couldn\'t open file", ioexception1);
			}
		}

		boolean flag = false;

		try {
			Class<?> oclass = Class.forName("java.awt.Desktop");
			Object object = oclass.getMethod("getDesktop", new Class[0]).invoke((Object) null, new Object[0]);
			oclass.getMethod("browse", new Class[] { URI.class }).invoke(object, new Object[] { fileIn.toURI() });
		} catch (Throwable throwable) {
		//	LOGGER.error("Couldn\'t open link", throwable);
			flag = true;
		}

		if (flag) {
		//	LOGGER.info("Opening via system class!");
			Sys.openURL("file://" + s);
		}
	}
}
